{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "73bd968b-d970-4a05-94ef-4e7abf990827",
   "metadata": {},
   "source": [
    "Chapter 23\n",
    "\n",
    "# 矩阵伪逆\n",
    "Book_3《数学要素》 | 鸢尾花书：从加减乘除到机器学习 (第二版)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7171e532-c1b9-4020-af77-97a6d1672617",
   "metadata": {},
   "source": [
    "这段代码的目的是通过最小二乘法求解线性方程组，从而找到一个最佳的参数估计。给定矩阵 $A$ 和向量 $b$，我们希望找到一个向量 $x$ 使得 $Ax \\approx b$，即使得 $Ax$ 与 $b$ 的差异最小。\n",
    "\n",
    "首先，我们定义了一个矩阵 $A$，其包含了数据的特征或自变量，以及一个向量 $b$，它包含了对应的观测值或因变量。然后，我们使用最小二乘法的公式来计算参数向量 $x$：\n",
    "\n",
    "$$\n",
    "x = (A^T A)^{-1} A^T b\n",
    "$$\n",
    "\n",
    "这里，$A^T$ 是 $A$ 的转置，$A^T A$ 是 $A$ 的自乘矩阵，通常称为设计矩阵。我们首先计算 $A^T A$，然后求其逆，接着用它乘以 $A^T$ 和 $b$，最终得到参数向量 $x$。\n",
    "\n",
    "这个过程可以看作是最小化平方误差的优化问题。我们的目标是最小化以下目标函数：\n",
    "\n",
    "$$\n",
    "\\text{minimize} \\quad ||Ax - b||^2\n",
    "$$\n",
    "\n",
    "通过求解这个优化问题，我们可以找到最佳的线性组合参数，从而使得模型的预测值 $Ax$ 尽可能接近观测值 $b$。\n",
    "\n",
    "最后，程序输出计算得到的 $x$ 值，即最佳的参数估计。这些参数可以用来进一步分析或进行预测。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "44ef8b02-c4e2-4d39-bb00-1fe9166b02d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d2a498a9-8d90-41ab-8cca-b6f8a47c0111",
   "metadata": {},
   "outputs": [],
   "source": [
    "A = np.array([[1,1],  # 定义矩阵A\n",
    "              [1,1],\n",
    "              [2,4],\n",
    "              [2,4]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "6616eaae-4422-4563-a5a9-741176e042d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "b = np.array([[30],  # 定义矩阵b\n",
    "              [35],\n",
    "              [90],\n",
    "              [110]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "43a3e18e-676d-4ff7-a47a-7d395490a9d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "x = np.linalg.inv(A.T@A)@A.T@b  # 计算线性方程的最小二乘解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "ecd518a4-820f-44ea-9e8f-baad55ee08d8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[15. ]\n",
      " [17.5]]\n"
     ]
    }
   ],
   "source": [
    "print(x)  # 输出结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "85a80909-2aac-49ed-bb7a-f8cc6b80ee7d",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ecd322f4-f919-4be2-adc3-69d28ef25e69",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
